ctypes

您所在的位置:网站首页 Python类的对象 指针 ctypes

ctypes

2024-07-14 07:26| 来源: 网络整理| 查看: 265

ctypes 参考手册¶ 寻找动态链接库¶

在编译型语言中,动态链接库会在编译、链接或者程序运行时访问。

find_library() 函数的目的是以类似于编译器或运行时加载器的方式来定位库(在有多个共享库版本的平台上应当加载最新的版本),而 ctypes 库加载器的行为类似于程序已经运行时直接调用运行时加载器。

ctypes.util 模块提供了一个函数,可以帮助确定要加载的库。

ctypes.util.find_library(name)

尝试寻找一个库然后返回其路径名, name 是库名称, 且去除了 lib 等前缀和 .so 、 .dylib 、版本号等后缀(这是 posix 连接器 -l 选项使用的格式)。如果没有找到对应的库,则返回 None 。

确切的功能取决于系统。

在 Linux 中,find_library() 会尝试运行外部程序 (/sbin/ldconfig, gcc, objdump 和 ld) 来查找库文件。 它会返回库文件的文件名。

在 3.6 版本发生变更: 在Linux 上,如果其他方式找不到的话,会使用环境变量 LD_LIBRARY_PATH 搜索动态链接库。

这是一些例子:

>>> from ctypes.util import find_library >>> find_library("m") 'libm.so.6' >>> find_library("c") 'libc.so.6' >>> find_library("bz2") 'libbz2.so.1.0' >>>

在 macOS 上,find_library() 会尝试几种预定义的命名方案和路径来查找库,并在成功时返回完整路径名:

>>> from ctypes.util import find_library >>> find_library("c") '/usr/lib/libc.dylib' >>> find_library("m") '/usr/lib/libm.dylib' >>> find_library("bz2") '/usr/lib/libbz2.dylib' >>> find_library("AGL") '/System/Library/Frameworks/AGL.framework/AGL' >>>

在 Windows 中,find_library() 会沿着系统搜索路径进行搜索,并返回完整的路径名称,但由于没有预定义的命名方案因此像 find_library("c") 这样的调用会失败并返回 None。

如果使用 ctypes 包装一个共享库,则更好的做法 可能 是开发时就确定好共享库的名称,并将其硬编码到包装模块中而不是在运行时使用 find_library() 来定位库。

加载动态链接库¶

有很多方式可以将动态链接库加载到 Python 进程。其中之一是实例化以下类的其中一个:

class ctypes.CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None)¶

该类的实例代表已加载的共享库。 这些库中的函数使用标准的 C 调用约定,并被预期会返回 int。

在 Windows 上创建 CDLL 实例可能会失败,即使 DLL 名称确实存在。 当某个被加载 DLL 所依赖的 DLL 未找到时,将引发 OSError 错误并附带消息 "[WinError 126] The specified module could not be found". 此错误消息不包含缺失 DLL 的名称,因为 Windows API 并不会返回此类信息,这使得此错误难以诊断。 要解决此错误并确定是哪一个 DLL 未找到,你需要找出所依赖的 DLL 列表并使用 Windows 调试与跟踪工具确定是哪一个未找到。

在 3.12 版本发生变更: 现在 name 形参可以是一个 path-like object。

参见

Microsoft DUMPBIN 工具 -- 一个用于查找 DLL 依赖的工具。

class ctypes.OleDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None)¶

仅 Windows : 此类的实例即加载好的动态链接库,其中的函数使用 stdcall 调用约定,并且假定返回 windows 指定的 HRESULT 返回码。 HRESULT 的值包含的信息说明函数调用成功还是失败,以及额外错误码。 如果返回值表示失败,会自动抛出 OSError 异常。

在 3.3 版本发生变更: 过去会引发 WindowsError,现在它是 OSError 的别名。

在 3.12 版本发生变更: 现在 name 形参可以是一个 path-like object。

class ctypes.WinDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False, winmode=None)¶

仅限 Windows:该类的实例代表已加载的共享库,这些库中的函数使用 stdcall 调用约定,并被预期默认会返回 int。

在 3.12 版本发生变更: 现在 name 形参可以是一个 path-like object。

调用动态库导出的函数之前,Python会释放 global interpreter lock ,并在调用后重新获取。

class ctypes.PyDLL(name, mode=DEFAULT_MODE, handle=None)¶

这个类实例的行为与 CDLL 类似,只不过 不会 在调用函数的时候释放 GIL 锁,且调用结束后会检查 Python 错误码。 如果错误码被设置,会抛出一个 Python 异常。

所以,它只在直接调用 Python C 接口函数的时候有用。

在 3.12 版本发生变更: 现在 name 形参可以是一个 path-like object。

所有这些类都可以传入至少一个参数作为共享库的路径名来实例化。 如果你有一个已经加载的共享库的句柄,可以将其作为``handle`` 参数传递,否则,底层平台的 dlopen() 或 LoadLibrary() 函数将用于将库加载到进程中,并获取其句柄。

mode 可以指定库加载方式。详情请参见 dlopen(3) 手册页。 在 Windows 上, 会忽略 mode ,在 posix 系统上, 总是会加上 RTLD_NOW ,且无法配置。

对于 use_errno 参数,如果设为真,则 ctypes 会启用一种安全访问系统 errno 的机制。 ctypes 维护有系统 errno 的一个线程局部副本;如果调用传入了 use_errno=True 的外部函数,函数调用前 errno 的值将与 ctypes 的私有副本交换,函数调用后也进行同样的交换。

The function ctypes.get_errno() returns the value of the ctypes private copy, and the function ctypes.set_errno() changes the ctypes private copy to a new value and returns the former value.

当 use_last_error 形参设为真值时,为 Windows 错误代码也启用与由 GetLastError() 和 SetLastError() Windows API 函数管理相同的机制;ctypes.get_last_error() 和 ctypes.set_last_error() 会被用于请求和更改 Windows 错误代码的 ctypes 私有副本。

winmode 形参用于在 Windows 上指定库的加载方式(因为 mode 会被忽略)。 它接受任何对 Win32 API LoadLibraryEx 旗标形参来说合法的值。 当被省略时,默认使用表示最安全的 DLL 加载的旗标,这将避免 DLL 劫持等问题。 传入 DLL 的完整路径是确保正确加载库及其依赖的最安全的方式。

在 3.8 版本发生变更: 增加了 winmode 参数。

ctypes.RTLD_GLOBAL

用于 mode 参数的标识值。在此标识不可用的系统上,它被定义为整数0。

ctypes.RTLD_LOCAL

Flag to use as mode parameter. On platforms where this is not available, it is the same as RTLD_GLOBAL.

ctypes.DEFAULT_MODE

加载动态链接库的默认模式。在 OSX 10.3 上,它是 RTLD_GLOBAL ,其余系统上是 RTLD_LOCAL 。

这些类的实例没有共用方法。动态链接库的导出函数可以通过属性或者索引的方式访问。注意,通过属性的方式访问会缓存这个函数,因而每次访问它时返回的都是同一个对象。另一方面,通过索引访问,每次都会返回一个新的对象:

>>> from ctypes import CDLL >>> libc = CDLL("libc.so.6") # On Linux >>> libc.time == libc.time True >>> libc['time'] == libc['time'] False

还有下面这些属性可用,他们的名称以下划线开头,以避免和导出函数重名:

PyDLL._handle¶

用于访问库的系统句柄。

PyDLL._name¶

传入构造函数的库名称。

共享库也可以通过使用一个预制对象来加载,这种对象是 LibraryLoader 类的实例,具体做法是调用 LoadLibrary() 方法,或是将库作为加载器实例的属性来提取。

class ctypes.LibraryLoader(dlltype)¶

加载共享库的类。 dlltype 应当为 CDLL, PyDLL, WinDLL 或 OleDLL 类型之一。

__getattr__() 具有特殊的行为:它允许通过一个作为库加载器实例的属性访问共享库来加载它。 访问结果会被缓存,因此每次重复的属性访问都会返回相同的库。

LoadLibrary(name)¶

加载一个共享库到进程中并将其返回。 此方法总是返回一个新的库实例。

可用的预制库加载器有如下这些:

ctypes.cdll

创建 CDLL 实例。

ctypes.windll

仅限 Windows:创建 WinDLL 实例.

ctypes.oledll

仅限 Windows:创建 OleDLL 实例。

ctypes.pydll

创建 PyDLL 实例。

要直接访问 C Python api,可以使用一个现成的 Python 共享库对象:

ctypes.pythonapi

一个将 Python C API 函数作为属性公开出来的 PyDLL 实例。 请注意所有这些函数都应返回 C int,当然也并非总是如此,因此您必须分配正确的 restype 属性才能使用这些函数。

引发一个 审计事件 ctypes.dlopen,附带参数 name。

引发一个审计事件 ctypes.dlsym,附带参数 library, name。

引发一个审计事件 ctypes.dlsym/handle,附带参数 handle, name。

外部函数¶

正如之前小节的说明,外部函数可作为被加载共享库的属性来访问。 用此方式创建的函数对象默认接受任意数量的参数,接受任意 ctypes 数据实例作为参数,并且返回库加载器所指定的默认结果类型。 它们是一个私有类的实例:

class ctypes._FuncPtr¶

C 可调用外部函数的基类。

外部函数的实例也是兼容 C 的数据类型;它们代表 C 函数指针。

此行为可通过对外部函数对象的特殊属性赋值来自定义。

restype¶

分配一个 ctypes 类型来指定外部函数的结果类型。 使用 None 来表示 void,即不返回任何结果的函数。

赋值为一个非 ctypes 类型的可调用 Python 对象也是可以的,在这种情况下函数应返回 C int,并且该可调用对象将附带此整数被调用,以允许进一步的处理或错误检查。 这种用法已被弃用,为了更灵活地进行后续处理或错误检查请使用 ctypes 数据类型作为 restype 并将 errcheck 属性赋值为一个可调用对象。

argtypes¶

赋值为一个 ctypes 类型的元组来指定函数所接受的参数类型。 使用 stdcall 调用规范的函数只能附带与此元组长度相同数量的参数进行调用;使用 C 调用规范的函数还可接受额外的未指明参数。

当调用外部函数时,每个实际参数都会被传给 argtypes 元组中条目的 from_param() 类方法,该方法允许将实际参数适配为此外部函数所接受的对象。 例如,argtypes 元组中的 c_char_p 条目将使用 ctypes 转换规则把作为参数传入的字符串转换为字节串对象。

新特性:现在可以在 argtypes 中放入非 ctypes 类型的条目,但每个条目必须具有 from_param() 方法用于返回一个可作为参数的值(整数、字符串、ctypes 实例)。 这样就允许定义可将将自定义对象适配为函数参数的适配器。

errcheck¶

将一个 Python 函数或其他可调用对象赋值给此属性。 该可调用对象将附带三个及以上的参数被调用。

callable(result, func, arguments)

result 是外部函数返回的结果,由 restype 属性指明。

func 是外部函数对象本身,这样就允许重新使用相同的可调用对象来对多个函数进行检查或后续处理。

arguments 是一个包含最初传递给函数调用的形参的元组,这样就允许对所用参数的行为进行特别处理。

此函数所返回的对象将会由外部函数调用返回,但它还可以在外部函数调用失败时检查结果并引发异常。

exception ctypes.ArgumentError¶

此异常会在外部函数无法对某个传入参数执行转换时被引发。

在 Windows 上,当外部函数调用引发一个系统异常时(例如由于访问冲突),它将被捕获并被替换为适当的 Python 异常。 此外,还将引发一个审计事件 ctypes.set_exception 并附带参数 code,以允许审计钩子将原异常替换为它自己的异常。

引发一个审计事件 ctypes.call_function,附带参数 func_pointer, arguments。

函数原型¶

外部函数也可通过实例化函数原型来创建。 函数原型类似于 C 中的函数原型;它们在不定义具体实现的情况下描述了一个函数(返回类型、参数类型、调用约定)。 工厂函数必须使用函数所需要的结果类型和参数类型来调用,并可被用作装饰器工厂函数,在此情况下可以通过 @wrapper 语法应用于函数。 请参阅 回调函数 了解有关示例。

ctypes.CFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)¶

返回的函数原型会创建使用标准 C 调用约定的函数。 该函数在调用过程中将释放 GIL。 如果 use_errno 设为真值,则在调用之前和之后系统 errno 变量的 ctypes 私有副本会与真正的 errno 值进行交换;use_last_error 会为 Windows 错误码执行同样的操作。

ctypes.WINFUNCTYPE(restype, *argtypes, use_errno=False, use_last_error=False)¶

仅限 Windows:返回的函数原型会创建使用 stdcall 调用约定的函数。 该函数在调用过程中将会释放 GIL。 use_errno 和 use_last_error 具有与上文中相同的含义。

ctypes.PYFUNCTYPE(restype, *argtypes)¶

返回的函数原型会创建使用 Python 调用约定的函数。 该函数在调用过程中将 不会 释放 GIL。

这些工厂函数所创建的函数原型可通过不同的方式来实例化,具体取决于调用中的类型与数量:

prototype(address)

在指定地址上返回一个外部函数,地址值必须为整数。

prototype(callable)

基于 Python callable 创建一个 C 可调用函数(回调函数)。

prototype(func_spec[, paramflags])

返回由一个共享库导出的外部函数。 func_spec 必须为一个 2 元组 (name_or_ordinal, library)。 第一项是字符串形式的所导出函数名称,或小整数形式的所导出函数序号。 第二项是该共享库实例。

prototype(vtbl_index, name[, paramflags[, iid]])

返回将调用一个 COM 方法的外部函数。 vtbl_index 虚拟函数表中的索引。 name 是 COM 方法的名称。 iid 是可选的指向接口标识符的指针,它被用于扩展的错误报告。

COM 方法使用特殊的调用约定:除了在 argtypes 元组中指定的形参,它们还要求一个指向 COM 接口的指针作为第一个参数。

可选的 paramflags 形参会创建相比上述特性具有更多功能的外部函数包装器。

paramflags 必须为一个与 argtypes 长度相同的元组。

此元组中的每一项都包含有关形参的更多信息,它必须为包含一个、两个或更多条目的元组。

第一项是包含形参指令旗标组合的整数。

1

指定函数的一个输入形参。

2

输出形参。 外部函数会填入一个值。

4

默认为整数零值的输入形参。

可选的第二项是字符串形式的形参名称。 如果指定此项,则可以使用该形参名称来调用外部函数。

可选的第三项是该形参的默认值。

下面的例子演示了如何包装 Windows 的 MessageBoxW 函数以使其支持默认形参和命名参数。 相应的 Windows 头文件的 C 声明是这样的:

WINUSERAPI int WINAPI MessageBoxW( HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);

这是使用 ctypes 的包装:

>>> from ctypes import c_int, WINFUNCTYPE, windll >>> from ctypes.wintypes import HWND, LPCWSTR, UINT >>> prototype = WINFUNCTYPE(c_int, HWND, LPCWSTR, LPCWSTR, UINT) >>> paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "caption", "Hello from ctypes"), (1, "flags", 0) >>> MessageBox = prototype(("MessageBoxW", windll.user32), paramflags)

现在 MessageBox 外部函数可以通过以下方式来调用:

>>> MessageBox() >>> MessageBox(text="Spam, spam, spam") >>> MessageBox(flags=2, text="foo bar")

第二个例子演示了输出形参。 这个 win32 GetWindowRect 函数通过将指定窗口的维度拷贝至调用者必须提供的 RECT 结构体来提取这些值。 这是相应的 C 声明:

WINUSERAPI BOOL WINAPI GetWindowRect( HWND hWnd, LPRECT lpRect);

这是使用 ctypes 的包装:

>>> from ctypes import POINTER, WINFUNCTYPE, windll, WinError >>> from ctypes.wintypes import BOOL, HWND, RECT >>> prototype = WINFUNCTYPE(BOOL, HWND, POINTER(RECT)) >>> paramflags = (1, "hwnd"), (2, "lprect") >>> GetWindowRect = prototype(("GetWindowRect", windll.user32), paramflags) >>>

带有输出形参的函数如果输出形参存在单一值则会自动返回该值,或是当输出形参存在多个值时返回包含这些值的元组,因此当 GetWindowRect 被调用时现在将返回一个 RECT 实例。

输出形参数可以与 errcheck 协议相结合以执行进一步的输出处理和错误检查。 Win32``GetWindowRect`` API 函数返回一个 BOOL 来表示成功或失败,因此该函数可以执行错误检查,并在 API 调用失败时引发异常:

>>> def errcheck(result, func, args): ... if not result: ... raise WinError() ... return args ... >>> GetWindowRect.errcheck = errcheck >>>

如果 errcheck 函数原封不动地返回它所接收的参数元组,则 ctypes 会继续对输出形参执行正常处理。 如果你希望返回一个窗口坐标的元组而非 RECT 实例,可以在函数中检索字段并返回它们,常规处理将不会再执行:

>>> def errcheck(result, func, args): ... if not result: ... raise WinError() ... rc = args[1] ... return rc.left, rc.top, rc.bottom, rc.right ... >>> GetWindowRect.errcheck = errcheck >>> 工具函数¶ ctypes.addressof(obj)¶

以整数形式返回内存缓冲区地址。 obj 必须为一个 ctypes 类型的实例。

引发一个 审计事件 ctypes.addressof,附带参数 obj。

ctypes.alignment(obj_or_type)¶

返回一个 ctypes 类型的对齐要求。 obj_or_type 必须为一个 ctypes 类型或实例。

ctypes.byref(obj[, offset])¶

返回指向 obj 的轻量指针,该对象必须为一个 ctypes 类型的实例。 offset 默认值为零,且必须为一个将被添加到内部指针值的整数。

byref(obj, offset) 对应于这段 C 代码:

(((char *)&obj) + offset)

返回的对象只能被用作外部函数调用形参。 它的行为类似于 pointer(obj),但构造起来要快很多。

ctypes.cast(obj, type)¶

此函数类似于 C 的强制转换运算符。 它返回一个 type 的新实例,该实例指向与 obj 相同的内存块。 type 必须为指针类型,而 obj 必须为可以被作为指针来解读的对象。

ctypes.create_string_buffer(init_or_size, size=None)¶

此函数会创建一个可变的字符缓冲区。 返回的对象是一个 c_char 的 ctypes 数组。

init_or_size 必须是一个指明数组大小的整数,或者是一个将被用来初始化数组条目的字节串对象。

如果将一个字节串对象指定为第一个参数,则将使缓冲区大小比其长度多一项以便数组的最后一项为一个 NUL 终结符。 可以传入一个整数作为第二个参数以允许在不使用字节串长度的情况下指定数组大小。

引发一个 审计事件 ctypes.create_string_buffer,附带参数 init, size。

ctypes.create_unicode_buffer(init_or_size, size=None)¶

此函数会创建一个可变的 unicode 字符缓冲区。 返回的对象是一个 c_wchar 的 ctypes 数组。

init_or_size 必须是一个指明数组大小的整数,或者是一个将被用来初始化数组条目的字符串。

如果将一个字符串指定为第一个参数,则将使缓冲区大小比其长度多一项以便数组的最后一项为一个 NUL 终结符。 可以传入一个整数作为第二个参数以允许在不使用字符串长度的情况下指定数组大小。

引发一个 审计事件 ctypes.create_unicode_buffer,附带参数 init, size。

ctypes.DllCanUnloadNow()¶

仅限 Windows:此函数是一个允许使用 ctypes 实现进程内 COM 服务的钩子。 它将由 _ctypes 扩展 dll 所导出的 DllCanUnloadNow 函数来调用。

ctypes.DllGetClassObject()¶

仅限 Windows:此函数是一个允许使用 ctypes 实现进程内 COM 服务的钩子。 它将由 _ctypes 扩展 dll 所导出的 DllGetClassObject 函数来调用。

ctypes.util.find_library(name)¶

尝试寻找一个库并返回路径名称。 name 是库名称并且不带任何前缀如 lib 以及后缀如 .so,.dylib 或版本号(形式与 posix 链接器选项 -l 所用的一致)。 如果找不到库,则返回 None。

确切的功能取决于系统。

ctypes.util.find_msvcrt()¶

仅限 Windows:返回 Python 以及扩展模块所使用的 VC 运行时库的文件名。 如果无法确定库名称,则返回 None。

如果你需要通过调用 free(void *) 来释放内存,例如某个扩展模块所分配的内存,重要的一点是你应当使用分配内存的库中的函数。

ctypes.FormatError([code])¶

仅限 Windows:返回错误码 code 的文本描述。 如果未指定错误码,则会通过调用 Windows api 函数 GetLastError 来获得最新的错误码。

ctypes.GetLastError()¶

仅限 Windows:返回 Windows 在调用线程中设置的最新错误码。 此函数会直接调用 Windows GetLastError() 函数,它并不返回错误码的 ctypes 私有副本。

ctypes.get_errno()¶

返回调用线程中系统 errno 变量的 ctypes 私有副本的当前值。

引发一个 审计事件 ctypes.get_errno,不附带任何参数。

ctypes.get_last_error()¶

仅限 Windows:返回调用线程中系统 LastError 变量的 ctypes 私有副本的当前值。

引发一个 审计事件 ctypes.get_last_error,不附带任何参数。

ctypes.memmove(dst, src, count)¶

与标准 C memmove 库函数相同:将 count 个字节从 src 拷贝到 dst。 dst 和 src 必须为整数或可被转换为指针的 ctypes 实例。

ctypes.memset(dst, c, count)¶

与标准 C memset 库函数相同:将位于地址 dst 的内存块用 count 个字节的 c 值填充。 dst 必须为指定地址的整数或 ctypes 实例。

ctypes.POINTER(type, /)¶

创建并返回一个新的 ctypes 指针类型。 指针类型会被缓存并在内部重复使用,因此重复调用此函数耗费不大。 type 必须为 ctypes 类型。

ctypes.pointer(obj, /)¶

创建一个新的指针实例,指向 obj。 返回的对象类型为 POINTER(type(obj))。

注意:如果你只是想向外部函数调用传递一个对象指针,你应当使用更为快速的 byref(obj)。

ctypes.resize(obj, size)¶

此函数可改变 obj 的内部内存缓冲区大小,其参数必须为 ctypes 类型的实例。 没有可能将缓冲区设为小于对象类型的本机大小值,该值由 sizeof(type(obj)) 给出,但将缓冲区加大则是可能的。

ctypes.set_errno(value)¶

设置调用线程中系统 errno 变量的 ctypes 私有副本的当前值为 value 并返回原来的值。

引发一个 审计事件 ctypes.set_errno 附带参数 errno。

ctypes.set_last_error(value)¶

仅限 Windows:设置调用线程中系统 LastError 变量的 ctypes 私有副本的当前值为 value 并返回原来的值。

引发一个 审计事件 ctypes.set_last_error,附带参数 error。

ctypes.sizeof(obj_or_type)¶

返回 ctypes 类型或实例的内存缓冲区以字节表示的大小。 其功能与 C sizeof 运算符相同。

ctypes.string_at(ptr, size=-1)¶

返回位于 void *ptr 的字节串。 如果指定了 size,它将被用作字节串的大小,否则将假定字节串以零值结尾。

引发一个 审计事件 ctypes.string_at,附带参数 ptr, size。

ctypes.WinError(code=None, descr=None)¶

仅限 Windows:此函数可能是 ctypes 中命名得最糟糕的。 它会创建一个 OSError 的实例。 如果未指定 code,则会调用 GetLastError 来确定错误码。 如果未指定 descr,则会调用 FormatError() 来获取错误的文本描述。

在 3.3 版本发生变更: 过去会创建 WindowsError 的实例,现在它是 OSError 的别名。

ctypes.wstring_at(ptr, size=-1)¶

返回位于 void *ptr 的宽字符串。 如果指定了 size,它将被用作字符串的字符数量,否则将假定字符串以零值结尾。

引发一个 审计事件 ctypes.wstring_at,附带参数 ptr, size。

数据类型¶ class ctypes._CData¶

这个非公有类是所有 ctypes 数据类型的共同基类。 另外,所有 ctypes 类型的实例都包含一个存放 C 兼容数据的内存块;该内存块的地址可由 addressof() 辅助函数返回。 还有一个实例变量被公开为 _objects;此变量包含其他在内存块包含指针的情况下需要保持存活的 Python 对象。

ctypes 数据类型的通用方法,它们都是类方法(严谨地说,它们是 metaclass 的方法):

from_buffer(source[, offset])¶

此方法返回一个共享 source 对象缓冲区的 ctypes 实例。 source 对象必须支持可写缓冲区接口。 可选的 offset 形参指定以字节表示的源缓冲区内偏移量;默认值为零。 如果源缓冲区不够大则会引发 ValueError。

引发一个 审计事件 ctypes.cdata/buffer 附带参数 pointer, size, offset。

from_buffer_copy(source[, offset])¶

此方法创建一个 ctypes 实例,从 source 对象缓冲区拷贝缓冲区,该对象必须是可读的。 可选的 offset 形参指定以字节表示的源缓冲区内偏移量;默认值为零。 如果源缓冲区不够大则会引发 ValueError。

引发一个 审计事件 ctypes.cdata/buffer 附带参数 pointer, size, offset。

from_address(address)¶

此方法会使用 address 所指定的内存返回一个 ctypes 类型的实例,该参数必须为一个整数。

引发一个 审计事件 ctypes.cdata,附带参数 address。

from_param(obj)¶

此方法会将 obj 适配为一个 ctypes 类型。 当该类型出现在外部函数的 argtypes 元组中时它将会被调用并传入在该外部函数中使用的实际对象;它必须返回一个可被用作函数调用参数的对象。

所有 ctypes 数据类型都带有这个类方法的默认实现,它通常会返回 obj,如果该对象是此类型的实例的话。 某些类型也能接受其他对象。

in_dll(library, name)¶

此方法返回一个由共享库导出的 ctypes 类型。 name 为导出数据的符号名称,library 为所加载的共享库。

ctypes 数据类型的通用实例变量:

_b_base_¶

有时 ctypes 数据实例并不拥有它们所包含的内存块,它们只是共享了某个基对象的部分内存块。 _b_base_ 只读成员是拥有内存块的根 ctypes 对象。

_b_needsfree_¶

这个只读变量在 ctypes 数据实例自身已分配了内存块时为真值,否则为假值。

_objects¶

这个成员或者为 None,或者为一个包含需要保持存活以使内存块的内存保持有效的 Python 对象的字典。 这个对象只是出于调试目的而对外公开;绝对不要修改此字典的内容。

基础数据类型¶ class ctypes._SimpleCData¶

这个非公有类是所有基本 ctypes 数据类型的基类。 它在这里被提及是因为它包含基本 ctypes 数据类型共有的属性。 _SimpleCData 是 _CData 的子类,因此继承了其方法和属性。 非指针及不包含指针的 ctypes 数据类型现在将可以被封存。

实例拥有一个属性:

value¶

这个属性包含实例的实际值。 对于整数和指针类型,它是一个整数,对于字符类型,它是一个单字符字符串对象或字符串,对于字符指针类型,它是一个 Python 字节串对象或字符串。

当从 ctypes 实例提取 value 属性时,通常每次会返回一个新的对象。 ctypes 并 没有 实现原始对象返回,它总是会构造一个新的对象。 所有其他 ctypes 对象实例也同样如此。

基本数据类型当作为外部函数调用结果被返回或者作为结构字段成员或数组项被提取时,会被透明地转换为原生 Python 类型。 换句话说,如果某个外来函数的 restype 是 c_char_p,那么你将总是得到一个 Python 字节串对象,而 不是 一个 c_char_p 实例。

基本数据类型的子类 不会 继承这种行为。 因此,如果一个外部函数的 restype 是 c_void_p 的子类,则你将从函数调用得到一个该子类的实例。 当然,你可以通过访问 value 属性来获取指针的值。

这些是基本 ctypes 数据类型:

class ctypes.c_byte¶

代表 C signed char 数据类型,并将值解读为一个小整数。 该构造器接受一个可选的整数初始值;不会执行溢出检查。

class ctypes.c_char¶

代表 C char 数据类型,并将值解读为单个字符。 该构造器接受一个可选的字符串初始值,字符串的长度必须恰好为一个字符。

class ctypes.c_char_p¶

当指向一个以零为结束符的字符串时代表 C char* 数据类型。 对于通用字符指针来说也可能指向二进制数据,必须要使用 POINTER(c_char)。 该构造器接受一个整数地址,或者一个字节串对象。

class ctypes.c_double¶

代表 C double 数据类型。 该构造器接受一个可选的浮点数初始值。

class ctypes.c_longdouble¶

代表 C long double 数据类型。 该构造器接受一个可选的浮点数初始值。 在 sizeof(long double) == sizeof(double) 的平台上它是 c_double 的一个别名。

class ctypes.c_float¶

代表 C float 数据类型。 该构造器接受一个可选的浮点数初始值。datatype. The constructor accepts an optional float initializer.

class ctypes.c_int¶

代表 C signed int 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。 在 sizeof(int) == sizeof(long) 的平台上它是 c_long 的一个别名。

class ctypes.c_int8¶

代表 C 8 位 signed int 数据类型。 通常是 c_byte 的一个别名。

class ctypes.c_int16¶

代表 C 16 位 signed int 数据类型。 通常是 c_short 的一个别名。

class ctypes.c_int32¶

代表 C 32 位 signed int 数据类型。 通常是 c_int 的一个别名。

class ctypes.c_int64¶

代表 C 64 位 signed int 数据类型。 通常是 c_longlong 的一个别名。

class ctypes.c_long¶

代表 C signed long 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。

class ctypes.c_longlong¶

代表 C signed long long 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。

class ctypes.c_short¶

代表 C signed short 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。

class ctypes.c_size_t¶

代表 C size_t 数据类型。

class ctypes.c_ssize_t¶

代表 C ssize_t 数据类型。

Added in version 3.2.

class ctypes.c_time_t¶

代表 C time_t 数据类型。

Added in version 3.12.

class ctypes.c_ubyte¶

代表 C unsigned char 数据类型,它将值解读为一个小整数。 该构造器接受一个可选的整数初始值;不会执行溢出检查。

class ctypes.c_uint¶

代表 C unsigned int 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。 在 sizeof(int) == sizeof(long) 的平台上它是 c_ulong 的一个别名。

class ctypes.c_uint8¶

代表 C 8 位 unsigned int 类型。 通常是 c_ubyte 的一个别名。.

class ctypes.c_uint16¶

代表 C 16 位 unsigned int 数据类型。 通常是 c_ushort 的一个别名。.

class ctypes.c_uint32¶

代表 C 32 位 unsigned int 数据类型。 通常是 c_uint 的一个别名。

class ctypes.c_uint64¶

代表 C 64 位 unsigned int 数据类型。 通常是 c_ulonglong 的一个别名。

class ctypes.c_ulong¶

代表 C unsigned long 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。

class ctypes.c_ulonglong¶

代表 C unsigned long long 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。

class ctypes.c_ushort¶

代表 C unsigned short 数据类型。 该构造器接受一个可选的整数初始值;不会执行溢出检查。

class ctypes.c_void_p¶

代表 C void* 类型。 该值被表示为整数形式。 该构造器接受一个可选的整数初始值。

class ctypes.c_wchar¶

代表 C wchar_t 数据类型,并将值解读为一单个字符的 unicode 字符串。 该构造器接受一个可选的字符串初始化器,字符串的长度必须恰好为一个字符。

class ctypes.c_wchar_p¶

代表 C wchar_t* 数据类型,它必须为指向以零为续签符的宽字符串的指针。 该构造器接受一个整数地址,或一个字符串。

class ctypes.c_bool¶

代表 C bool 数据类型 (更准确地说,是 C99 _Bool)。 它的值可以为 True 或 False,并且该构造器接受任何具有逻辑值的对象。

class ctypes.HRESULT¶

仅限 Windows:代表一个 HRESULT 值,它包含某个函数或方法调用的成功或错误信息。

class ctypes.py_object¶

代表 C PyObject* 数据类型。 不带参数地调用此构造器将创建一个 NULL PyObject* 指针。

ctypes.wintypes 模块提供了其他许多 Windows 专属的数据类型,例如 HWND, WPARAM 或 DWORD。 还定义了一些有用的结构体如 MSG 或 RECT。

结构化数据类型¶ class ctypes.Union(*args, **kw)¶

本机字节序的联合所对应的抽象基类。

class ctypes.BigEndianUnion(*args, **kw)¶

大端 字节序的联合所对应的抽象基类。

Added in version 3.11.

class ctypes.LittleEndianUnion(*args, **kw)¶

小端 字节序的联合所对应的抽象基类。

Added in version 3.11.

class ctypes.BigEndianStructure(*args, **kw)¶

大端 字节序的结构体所对应的抽象基类。

class ctypes.LittleEndianStructure(*args, **kw)¶

小端 字节序的结构体所对应的抽象基类。

非本机字节序的结构体和联合不能包含指针类型字段,或任何其他包含指针类型字段的数据类型。

class ctypes.Structure(*args, **kw)¶

本机 字节序的结构体所对应的抽象基类。

实际的结构体和联合类型必须通过子类化这些类型之一来创建,并且至少要定义一个 _fields_ 类变量。 ctypes 将创建 descriptor,它允许通过直接属性访问来读取和写入字段。 这些是

_fields_¶

一个定义结构体字段的序列。 其中的条目必须为 2 元组或 3 元组。 元组的第一项是字段名称,第二项指明字段类型;它可以是任何 ctypes 数据类型。

对于整数类型字段例如 c_int,可以给定第三个可选项。 它必须是一个定义字段比特位宽度的小正整数。

字段名称在一个结构体或联合中必须唯一。 不会检查这个唯一性,但当名称出现重复时将只有一个字段可被访问。

可以在定义 Structure 子类的类语句 之后 再定义 _fields_ 类变量,这将允许创建直接或间接引用其自身的数据类型:

class List(Structure): pass List._fields_ = [("pnext", POINTER(List)), ... ]

但是,_fields_ 类变量必须在类型第一次被使用(创建实例,调用 sizeof() 等等)之前进行定义。 在此之后对 _fields_ 类变量赋值将会引发 AttributeError。

可以定义结构体类型的子类,它们会继承基类的字段再加上在子类中定义的任何 _fields_。

_pack_¶

一个可选的小整数,它允许覆盖实例中结构体字段的对齐方式。 当 _fields_ 被赋值时必须已经定义了 _pack_,否则它将没有效果。 将该属性设为 0 的效果与不设置它一样。

_anonymous_¶

一个可选的序列,它会列出未命名(匿名)字段的名称。 当 _fields_ 被赋值时必须已经定义了 _anonymous_,否则它将没有效果。

在此变量中列出的字段必须为结构体或联合类型字段。 ctypes 将在结构体类型中创建描述器以允许直接访问嵌套字段,而无需创建对应的结构体或联合字段。

以下是一个示例类型(Windows):

class _U(Union): _fields_ = [("lptdesc", POINTER(TYPEDESC)), ("lpadesc", POINTER(ARRAYDESC)), ("hreftype", HREFTYPE)] class TYPEDESC(Structure): _anonymous_ = ("u",) _fields_ = [("u", _U), ("vt", VARTYPE)]

TYPEDESC 结构体描述了一个 COM 数据类型,vt 字段指明哪个联合字段是有效的。 由于 u 字段被定义为匿名字段,现在可以直接从 TYPEDESC 实例访问成员。 td.lptdesc 和 td.u.lptdesc 是等价的,但前者速度更快,因为它不需要创建临时的联合实例:

td = TYPEDESC() td.vt = VT_PTR td.lptdesc = POINTER(some_type) td.u.lptdesc = POINTER(some_type)

可以定义结构体的子类,它们会继承基类的字段。 如果子类定义具有单独的 _fields_ 变量,在其中指定的字段会被添加到基类的字段中。

结构体和联合的构造器均可接受位置和关键字参数。 位置参数用于按照 _fields_ 中的出现顺序来初始化成员字段。 构造器中的关键字参数会被解读为属性赋值,因此它们将以相应的名称来初始化 _fields_,或为不存在于 _fields_ 中的名称创建新的属性。

数组与指针¶ class ctypes.Array(*args)¶

数组的抽象基类。

创建实体数组类型的推荐方式是通过将任意 ctypes 数据类型与一个非负整数相乘。 作为替代方式,你也可以子类化这个类型并定义 _length_ 和 _type_ 类变量。 数组元素可使用标准的抽取和切片操作来进行读写;对于切片读取,结果对象本身 不是 一个 Array。

_length_¶

一个指明数组中元素数量的正整数。 超出范围的抽取会导致 IndexError。 该值将由 len() 返回。

_type_¶

指明数组中每个元素的类型。

Array 子类构造器可接受位置参数,用来按顺序初始化元素。

class ctypes._Pointer¶

私有对象,指针的抽象基类。

实际的指针类型是通过调用 POINTER() 并附带其将指向的类型来创建的;这会由 pointer() 自动完成。

如果一个指针指向的是数组,则其元素可使用标准的抽取和切片方式来读写。 指针对象没有长度,因此 len() 将引发 TypeError。 抽取负值将会从指针 之前 的内存中读取(与 C 一样),并且超出范围的抽取将可能因非法访问而导致崩溃(视你的运气而定)。

_type_¶

指明所指向的类型。

contents¶

返回指针所指向的对象。 对此属性赋值会使指针改为指向所赋值的对象。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3